using LiteDB;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DidaManager.Log;

namespace LiteDb
{
    /// <summary>
    /// 设备数据库连接管理器
    /// </summary>
    public class DeviceDbConnectionManager : IDisposable
    {
        private readonly MultiDbConfiguration _config;
        private readonly ConcurrentDictionary<int, LiteDatabase> _deviceConnections = new();
        private readonly ConcurrentDictionary<int, CefSharpServer> _deviceServers = new();
        private readonly object _lock = new object();
        private readonly string _mainDbPath;

        public DeviceDbConnectionManager(MultiDbConfiguration config)
        {
            _config = config;
            _mainDbPath = Path.Combine(_config.BasePath, _config.MainDbFileName);
            
            // 确保目录存在
            if (!Directory.Exists(_config.BasePath))
            {
                Directory.CreateDirectory(_config.BasePath);
                LogManager.Info($"创建设备数据库目录: {_config.BasePath}");
            }
        }

        /// <summary>
        /// 根据设备ID获取对应的分组ID
        /// </summary>
        public int GetGroupIdByDeviceId(int deviceId)
        {
            try
            {
                using var mainDb = new LiteDatabase($"Filename={_mainDbPath};Connection=shared");
                var deviceCollection = mainDb.GetCollection<GroupDevice>(GroupDevice.CollectionName);
                var device = deviceCollection.FindById(deviceId);
                return device?.GroupId ?? 1; // 默认分组ID为1
            }
            catch (Exception ex)
            {
                LogManager.Warn($"查询设备分组ID失败，使用默认分组: {ex.Message}");
                return 1; // 默认分组ID为1
            }
        }

        /// <summary>
        /// 获取设备数据库路径
        /// </summary>
        public string GetDeviceDatabasePath(int deviceId, int groupId)
        {
            var groupFolder = string.Format(_config.GroupFolderTemplate, groupId);
            var deviceFileName = string.Format(_config.DeviceDbTemplate, deviceId);
            return Path.Combine(_config.BasePath, groupFolder, deviceFileName);
        }

        /// <summary>
        /// 获取设备数据库连接
        /// </summary>
        public LiteDatabase GetDeviceDatabase(int deviceId)
        {
            if (_config.EnableConnectionPool && _deviceConnections.TryGetValue(deviceId, out var existingDb))
            {
                return existingDb;
            }

            lock (_lock)
            {
                if (_config.EnableConnectionPool && _deviceConnections.TryGetValue(deviceId, out existingDb))
                {
                    return existingDb;
                }

                // 获取设备对应的分组ID
                var groupId = GetGroupIdByDeviceId(deviceId);
                var dbPath = GetDeviceDatabasePath(deviceId, groupId);
                
                // 确保数据库文件所在目录存在
                var directory = Path.GetDirectoryName(dbPath);
                if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                    LogManager.Info($"创建分组数据库目录: {directory}");
                }
                
                // 检查数据库文件是否已存在
                bool isNewDatabase = !File.Exists(dbPath);
                
                var connectionString = string.Format(_config.ConnectionStringTemplate, dbPath);
                var db = new LiteDatabase(connectionString);
                
                if (isNewDatabase)
                {
                    // 对于新创建的数据库，确保文件被写入磁盘
                    try
                    {
                        // 最简单的方式：获取一个集合，这会触发数据库文件的创建
                        var collection = db.GetCollection("monitor_ports");
                        collection.EnsureIndex("Id");
                        
                        // 强制刷新到磁盘
                        db.Checkpoint();
                        
                        LogManager.Info($"创建新的设备数据库: {dbPath}");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warn($"初始化新数据库时出现问题: {ex.Message}");
                    }
                }
                else
                {
                    LogManager.Debug($"连接到现有设备数据库: {dbPath}");
                }
                
                if (_config.EnableConnectionPool)
                {
                    _deviceConnections.TryAdd(deviceId, db);
                }
                
                return db;
            }
        }

        /// <summary>
        /// 获取设备的CefSharpServer
        /// </summary>
        public CefSharpServer GetDeviceCefSharpServer(int deviceId)
        {
            if (_deviceServers.TryGetValue(deviceId, out var existingServer))
            {
                return existingServer;
            }

            lock (_lock)
            {
                if (_deviceServers.TryGetValue(deviceId, out existingServer))
                {
                    return existingServer;
                }

                try
                {
                    var deviceDb = GetDeviceDatabase(deviceId);
                    var server = new CefSharpServer(deviceDb);
                    _deviceServers.TryAdd(deviceId, server);
                    
                    LogManager.Debug($"已创建设备CefSharpServer: device_{deviceId}");
                    return server;
                }
                catch (Exception ex)
                {
                    LogManager.Error($"创建设备CefSharpServer失败 (deviceId: {deviceId}): {ex.Message}", ex);
                    throw new InvalidOperationException($"无法为设备 {deviceId} 创建CefSharpServer。错误详情: {ex.Message}", ex);
                }
            }
        }

        /// <summary>
        /// 强制关闭设备数据库连接（用于文件操作前释放资源）
        /// </summary>
        public void ForceCloseDeviceDatabase(int deviceId)
        {
            try
            {
                // 强制关闭连接和服务器
                if (_deviceConnections.TryRemove(deviceId, out var db))
                {
                    db.Dispose();
                    LogManager.Info($"已强制关闭设备数据库连接: device_{deviceId}.db");
                }
                
                if (_deviceServers.TryRemove(deviceId, out var server))
                {
                    // CefSharpServer没有Dispose方法，不需要释放
                    LogManager.Info($"已移除设备服务器: device_{deviceId}.db");
                }

                // 强制垃圾回收，确保文件句柄被释放
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                
                // 等待一小段时间，确保文件句柄完全释放
                System.Threading.Thread.Sleep(100);
            }
            catch (Exception ex)
            {
                LogManager.Error($"强制关闭设备数据库连接时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 删除设备数据库文件
        /// </summary>
        public bool DeleteDeviceDatabase(int deviceId, int groupId)
        {
            try
            {
                // 关闭连接和服务器
                if (_deviceConnections.TryRemove(deviceId, out var db))
                {
                    db.Dispose();
                    LogManager.Debug($"已关闭设备数据库连接: device_{deviceId}.db");
                }
                
                if (_deviceServers.TryRemove(deviceId, out var server))
                {
                    // CefSharpServer没有Dispose方法，不需要释放
                    LogManager.Debug($"已移除设备服务器: device_{deviceId}.db");
                }

                // 获取设备对应的分组ID和文件路径
                //var groupId = GetGroupIdByDeviceId(deviceId);
                var dbPath = GetDeviceDatabasePath(deviceId, groupId);
                
                if (File.Exists(dbPath))
                {
                    File.Delete(dbPath);
                    LogManager.Info($"已删除设备数据库文件: {dbPath}");
                    
                    // 检查分组文件夹是否为空，如果为空则删除文件夹
                    var groupFolder = Path.GetDirectoryName(dbPath);
                    if (!string.IsNullOrEmpty(groupFolder) && Directory.Exists(groupFolder))
                    {
                        try
                        {
                            var filesInGroup = Directory.GetFiles(groupFolder, "*.db");
                            if (filesInGroup.Length == 0)
                            {
                                Directory.Delete(groupFolder);
                                LogManager.Info($"已删除空的分组文件夹: {groupFolder}");
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Warn($"清理分组文件夹时出现问题: {ex.Message}");
                        }
                    }
                    
                    return true;
                }
                else
                {
                    LogManager.Warn($"设备数据库文件不存在: {dbPath}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"删除设备数据库失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取所有设备数据库文件
        /// </summary>
        public List<string> GetAllDeviceDatabaseFiles()
        {
            var files = new List<string>();
            
            if (!Directory.Exists(_config.BasePath))
            {
                return files;
            }
            
            try
            {
                // 查找所有分组文件夹
                var groupFolders = Directory.GetDirectories(_config.BasePath, "group_*");
                
                foreach (var groupFolder in groupFolders)
                {
                    // 在每个分组文件夹中查找设备数据库文件
                    var deviceFiles = Directory.GetFiles(groupFolder, "device_*.db");
                    files.AddRange(deviceFiles);
                }
                
                LogManager.Debug($"找到 {files.Count} 个设备数据库文件");
                return files;
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取设备数据库文件列表失败: {ex.Message}", ex);
                return files;
            }
        }

        /// <summary>
        /// 安全的文件复制方法，带重试机制
        /// </summary>
        public bool SafeFileCopy(string sourcePath, string destPath, int maxRetries = 3, int retryDelayMs = 500)
        {
            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    // 确保目标目录存在
                    var destDir = Path.GetDirectoryName(destPath);
                    if (!string.IsNullOrEmpty(destDir) && !Directory.Exists(destDir))
                    {
                        Directory.CreateDirectory(destDir);
                    }

                    // 如果目标文件存在，先尝试删除
                    if (File.Exists(destPath))
                    {
                        File.SetAttributes(destPath, FileAttributes.Normal);
                        File.Delete(destPath);
                    }

                    // 执行文件复制
                    File.Copy(sourcePath, destPath, true);
                    LogManager.Info($"文件复制成功: {sourcePath} -> {destPath}");
                    return true;
                }
                catch (IOException ex) when (ex.Message.Contains("正在使用") || ex.Message.Contains("being used") || ex.Message.Contains("access denied"))
                {
                    LogManager.Warn($"文件复制失败 (第{i + 1}次尝试): {ex.Message}");
                    
                    if (i < maxRetries - 1)
                    {
                        // 强制垃圾回收
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        GC.Collect();
                        
                        // 等待后重试
                        System.Threading.Thread.Sleep(retryDelayMs);
                        LogManager.Info($"等待 {retryDelayMs}ms 后重试文件复制...");
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"文件复制出现未预期错误: {ex.Message}", ex);
                    return false;
                }
            }
            
            LogManager.Error($"文件复制失败，已重试 {maxRetries} 次: {sourcePath} -> {destPath}");
            return false;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            foreach (var db in _deviceConnections.Values)
            {
                db?.Dispose();
            }
            _deviceConnections.Clear();
            _deviceServers.Clear();
        }
    }
}

